package com.histone.lilian.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.springframework.stereotype.Component;
import org.ssssssss.magicapi.core.context.RequestEntity;
import org.ssssssss.magicapi.core.interceptor.RequestInterceptor;
import org.ssssssss.magicapi.core.interceptor.ResultProvider;
import org.ssssssss.magicapi.core.model.ApiInfo;
import org.ssssssss.magicapi.core.model.JsonBean;
import org.ssssssss.magicapi.core.model.Options;
import org.ssssssss.script.MagicScriptContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * magic-api 接口鉴权、处理返回结果、处理异常
 */
@Component
public class MagicApiInterceptor implements RequestInterceptor, ResultProvider {

    private static final Log log = LogFactory.get();

    /**
     * 接口请求之前
     * @param info	接口信息
     * @param context	脚本变量信息
     */
    @Override
    public Object preHandle(ApiInfo info, MagicScriptContext context, HttpServletRequest request, HttpServletResponse response) throws Exception {

        // 接口选项配置了需要登录
        if ("true".equals(info.getOptionValue(Options.REQUIRE_LOGIN)) && !StpUtil.isLogin()) {
            return new JsonBean<>(401, "用户未登录");
        }
        String role = info.getOptionValue(Options.ROLE);
        if (StrUtil.isNotBlank(role)) {
            if (!StpUtil.isLogin()) {
                return new JsonBean<>(401, "用户未登录");
            }
            if (StpUtil.hasRole("admin")) {
                return null;
            }
            List<String> roleList = StrUtil.split(role, ",");
            if (!StpUtil.hasRoleOr(ArrayUtil.toArray(roleList, String.class))) {
                return new JsonBean<>(403, "用户权限不足");
            }
        }

        String permission = info.getOptionValue(Options.PERMISSION);
        if (StrUtil.isNotBlank(permission)) {
            if (!StpUtil.isLogin()) {
                return new JsonBean<>(401, "用户未登录");
            }
            if (!StpUtil.hasRole("admin") && !StpUtil.hasPermissionOr(StrUtil.splitToArray(permission, ","))) {
                return new JsonBean<>(403, "用户权限不足");
            }
        }

        return null;
    }

    /**
     * 接口执行之后
     * @param info	接口信息
     * @param context	变量信息
     * @param value 即将要返回到页面的值
     */
    @Override
    public Object postHandle(ApiInfo info, MagicScriptContext context, Object value, HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.debug("{} 执行完毕，返回结果:{}", info.getName(), value);
        return null;
    }

    /**
     * 处理返回结果
     * @param requestEntity
     * @param code
     * @param message
     * @param data
     * @return
     */
    @Override
    public Object buildResult(RequestEntity requestEntity, int code, String message, Object data) {
        long timestamp = System.currentTimeMillis();
        return new JsonBean<>(code, message, data, (int) (timestamp - requestEntity.getRequestTime()));
    }


    /**
     * 处理异常
     * @param requestEntity
     * @param throwable
     * @return
     */
    @Override
    public Object buildException(RequestEntity requestEntity, Throwable throwable) {
        if (throwable.getCause() instanceof NotLoginException) {
            return this.buildResult(requestEntity, 401, "登录状态过期", null);
        }
        return buildResult(requestEntity, 500, "系统内部出现错误");
    }
}
